class CharacterManager
{
	private var playerList:Array;
	private var enemyList:Array;
	private var playerPeekabooList:Array;
	private var enemyPeekabooList:Array;
	private var mapReference:Map;
	private var moveDone:boolean;
	private var AImoveDone:boolean;
	private var numPlayersDone:int; //keep track of the amount of characters done with the movement
	private var numEnemiesDone:int;
	private var numEnemiesDead:int;
	private var numPlayersDead:int;

	private var _selectedPlayer:GameCharacter;
	private var _selectedHealTarget:GameCharacter;
	private var _lockSelectedPlayer:boolean;
	private var _waitingForPlayerSelection:boolean;
	
	private var _selectedEnemy:EnemyCharacter;
	private var _waitingForEnemySelection:boolean;
	
	public static var PLAYER_MELEE:int = 1;
	public static var PLAYER_RANGE:int = 2;
	public static var PLAYER_SPELL:int = 3;
	public static var PLAYER_HEALER:int = 4;
	public static var PLAYER_SCOUT:int = 5;
	
	public static var ENEMY_MELEE:int = 1;
	public static var ENEMY_RANGE:int = 2;	
	public static var ENEMY_SPELL:int = 3;
	public static var ENEMY_HEALER:int = 4;
	public static var ENEMY_SCOUT:int = 5;
	
	private var delay:int = 0;
	private var eindex:int = 0;
	
	private var pauseMode:boolean;
	
	enum AIDecision { PATROL, AIATTACK, AIMOVE, AIPEEKABOO, AI_ATTACKSKILL, AI_BUFFSKILL }
	class DecisionStruct extends System.ValueType 
	{
		var decision:AIDecision;
		var playerCharacter:GameCharacter;
		var enemyAllyCharacter:EnemyCharacter;
		var moveTile:Tile;		
		
		//Getters
		function getDecision(){ return decision; } 
		function getPlayerCharacter(){ return playerCharacter; } 
		function getEnemyAllyCharacter(){ return enemyAllyCharacter; }
		function getMoveTile(){ return moveTile; } 
		
		//Setters
		function setDecision(_decision:AIDecision){ decision = _decision; } 
		function setPlayerCharacter(_playerCharacter:GameCharacter){ playerCharacter = _playerCharacter; } 
		function setEnemyAllyCharacter(_enemyAllyCharacter:EnemyCharacter){ enemyAllyCharacter = _enemyAllyCharacter; } 
		function setMoveTile(_moveTile:Tile){ moveTile = _moveTile; } 
	}	
	
	function CharacterManager(map:Map)
	{
		playerList = new Array();
		enemyList = new Array();
		playerPeekabooList = new Array();
		enemyPeekabooList = new Array();
		mapReference = map;
		
		moveDone = true;
		AImoveDone = false;
		allPlayersMoved = false;
		
		_selectedPlayer = null;
		_selectedHealTarget = null;
		_lockSelectedPlayer = false;
		_waitingForPlayerSelection = false;
		
		_selectedEnemy = null;
		_waitingForEnemySelection = false;
				
		numPlayersDone = 0;
		numEnemiesDone = 0;

		pauseMode = false;
		
		numEnemiesDead = numPlayersDead = 0;
	}
	
	function CharacterManager()
	{
	
	}
	
	function setupMap(map:Map)
	{
		playerList = new Array();
		enemyList = new Array();
		playerPeekabooList = new Array();
		enemyPeekabooList = new Array();
		mapReference = map;
		
		moveDone = true;
		AImoveDone = false;
		allPlayersMoved = false;
		
		_selectedPlayer = null;
		_selectedHealTarget = null;
		_lockSelectedPlayer = false;
		_waitingForPlayerSelection = false;
		
		_selectedEnemy = null;
		_waitingForEnemySelection = false;
				
		numPlayersDone = 0;
		numEnemiesDone = 0;

		pauseMode = false;
		
		numEnemiesDead = numPlayersDead = 0;
	}	

	
	function spawnPlayer(characterType:int, startTile:Tile)
	{
		var characterModel;
		var character:GameObject;
		var characterRef:GameCharacter;
		
		switch(characterType)
		{
			case PLAYER_MELEE:
				characterModel = Resources.Load("Flavis_Melee");
				character = MonoBehaviour.Instantiate(characterModel);
				character.AddComponent(PlayerMelee);
				characterRef = character.GetComponent(PlayerMelee);
				break;
				
			case PLAYER_RANGE:
				characterModel = Resources.Load("Flavis_Archer");
				character = MonoBehaviour.Instantiate(characterModel);
				character.AddComponent(PlayerArcher);
				characterRef = character.GetComponent(PlayerArcher);				
				break;
				
			case PLAYER_HEALER:
				characterModel = Resources.Load("Flavis_Medic");
				character = MonoBehaviour.Instantiate(characterModel);
				character.AddComponent(PlayerHealer);
				characterRef = character.GetComponent(PlayerHealer);
				break;
				
			case PLAYER_SPELL:
				characterModel = Resources.Load("Flavis_Spellcaster");
				character = MonoBehaviour.Instantiate(characterModel);
				character.AddComponent(PlayerSpellCaster);
				characterRef = character.GetComponent(PlayerSpellCaster);				
				break;
				
			case PLAYER_SCOUT:
				characterModel = Resources.Load("Flavis_Scout");
				character = MonoBehaviour.Instantiate(characterModel);
				character.AddComponent(PlayerScout);
				characterRef = character.GetComponent(PlayerScout);
				break;
				
		}
		
		character.tag = "PlayerCharacter";
		characterRef.initAnimation();
		characterRef.setIsPlayer(true);
		characterRef.setManagerReference(this);
		characterRef.setMapReference(mapReference);
		characterRef.setTileReference(startTile);
		characterRef.setWorldCoord();
		playerList.Push(characterRef);
		
		if( playerList.length == 1 )
		{
			//Set camera position on first playable character
			var cam = GameObject.FindWithTag("MainCamera");
			cam.GetComponent("CameraOrbit").setCameraPos(playerList[0].transform.position.x,playerList[0].transform.position.z);
		}
	}
	
	function spawnEnemy(enemyType:int, startTile:Tile)
	{
		var enemyModel;
		var enemy:GameObject;
		var enemyRef;
		
		switch(enemyType)
		{
			case ENEMY_MELEE:
				enemyModel = Resources.Load("Purpura_Melee");	
				enemy = MonoBehaviour.Instantiate(enemyModel);			
				enemy.AddComponent(EnemyMelee);
				enemyRef = enemy.GetComponent(EnemyMelee);	
				break;
			case ENEMY_RANGE:
				enemyModel = Resources.Load("Purpura_Archer");
				enemy = MonoBehaviour.Instantiate(enemyModel);				
				enemy.AddComponent(EnemyArcher);
				enemyRef = enemy.GetComponent(EnemyArcher);	
				break;
			case ENEMY_SPELL:
				enemyModel = Resources.Load("Purpura_Spellcaster");	
				enemy = MonoBehaviour.Instantiate(enemyModel);			
				enemy.AddComponent(EnemySpellcaster);
				enemyRef = enemy.GetComponent(EnemySpellcaster);				
				break;
			case ENEMY_HEALER:
				enemyModel = Resources.Load("Purpura_Medic");	
				enemy = MonoBehaviour.Instantiate(enemyModel);			
				enemy.AddComponent(EnemyHealer);
				enemyRef = enemy.GetComponent(EnemyHealer);				
				break;
			case ENEMY_SCOUT:
				enemyModel = Resources.Load("Purpura_Scout");	
				enemy = MonoBehaviour.Instantiate(enemyModel);			
				enemy.AddComponent(EnemyMelee);
				enemyRef = enemy.GetComponent(EnemyMelee);				
				break;
		}
				
		
		enemy.tag = "EnemyCharacter";	
		enemyRef.initAnimation();
		enemyRef.setIsPlayer(false);
		enemyRef.setManagerReference(this);
		enemyRef.setMapReference(mapReference);
		enemyRef.setTileReference(startTile);
		enemyRef.setWorldCoord();
		enemyList.Push(enemyRef);
	}
	
	public function updateCharacter(tile:Tile)
	{
		if (!moveDone)
			return;
	
		//if no player selected
		if (_selectedPlayer == null)
		{
			
		}
		//player selected
		else
		{
			//move button clicked
			if (_selectedPlayer.getBtnClicked() == GameCharacter.MOVE_BTN)
			{
				//button selected, do not allow other players to be selected
				_lockSelectedPlayer = true;
				//a tile was clicked 
				if (tile != null)
				{
					//if tile is within move range of player
					if (_selectedPlayer.isWithinMoveRange(tile))
					{
						//unselect the player
						_selectedPlayer.Deselected();
						//move to tile
						_selectedPlayer.moveTo(tile);
						//clear btn clicked of the character
						_selectedPlayer.removeBtnClicked();
						//unlock and allow selection of other player
						_lockSelectedPlayer = false;
						//lock state to disallow selection of other things when moving
						moveDone = false;
						//remove player selected
						_selectedPlayer = null;
					}
				}
			}
			//attack button clicked
			else if (_selectedPlayer.getBtnClicked() == GameCharacter.ATK_BTN)
			{
				//button selected, do not allow other players to be selected
				_lockSelectedPlayer = true;
				
				//just clicked
				if (!_waitingForEnemySelection)
				{	
					//allow enemy selection
					_waitingForEnemySelection = true;
					//find list of enemies within range
					var enemiesInRange:Array = new Array();
					var atkRange = _selectedPlayer.getAttackRadius();
					var srcCoord:Vector2 = _selectedPlayer.getCoord();
					for (var i = 0; i < enemyList.length; i++)
					{
						var dstCoord :Vector2 = enemyList[i].getCoord();
						if (Vector2.Distance(srcCoord, dstCoord) <= atkRange && !enemyList[i].getIsDead())
						{
							//target is within range
							enemiesInRange.Push(enemyList[i]);
						}
					}
					//raycast to the list of enemies for visibility check
					var raySource:Vector3 = _selectedPlayer.getSurfaceCoord();
					var layerMask:int = 1 << LayerMask.NameToLayer("Obstacle");
					for (var j = 0; j < enemiesInRange.length; j++)
					{
						//convert target to be in obstacle layer so that raycast will include obstacles
						enemiesInRange[j].gameObject.layer = LayerMask.NameToLayer("Obstacle");
						var rayDst:Vector3 = enemiesInRange[j].getSurfaceCoord();
						var hit:RaycastHit;
						//raycast only to the enemy layer
						if (Physics.Raycast(raySource, rayDst - raySource, hit, atkRange,layerMask))
						{
							//casted enemies, setSelectable(true)
							if(hit.collider.gameObject.tag.Equals("EnemyCharacter")){
								enemiesInRange[j].setSelectable(true, _selectedPlayer.calculateHitChance(enemiesInRange[j])
																,enemiesInRange[j].isFlanked(_selectedPlayer));
																
								enemiesInRange[j].setGridTarget(0);
							}
						}
						//convert target back to enemy
						enemiesInRange[j].gameObject.layer = LayerMask.NameToLayer("Enemy");
					}	
					
					if(enemiesInRange.length == 0){
						var noRangeText = Resources.Load("Attackable_text");
						noRangeText = MonoBehaviour.Instantiate(noRangeText);
						noRangeText.transform.position = _selectedPlayer.getTileReference().getSurfaceCoord();
						noRangeText.transform.position.y += 2;
						noRangeText.GetComponent(AttackableText).setAutoRemoveText("Not in range", 40, 2);
						
						//unselect the player
						_selectedPlayer.Deselected();
						//clear btn clicked of the character
						_selectedPlayer.removeBtnClicked();
						
						_lockSelectedPlayer = false;
										
						//remove player selected
						_selectedPlayer = null;			
					}
				}
				else
				{
					//enemy selected
					if (_selectedEnemy != null)
					{
						//unselect the player
						_selectedPlayer.Deselected();
						//clear btn clicked of the character
						_selectedPlayer.removeBtnClicked();
						//unlock and allow selection of other player
						_lockSelectedPlayer = false;
						//lock state to disallow selection of other things when moving
						moveDone = false;
						
						//attack the enemy
						_selectedPlayer.attack(_selectedEnemy, Projectile.NORMAL);
						
						//remove player selected
						_selectedPlayer = null;			
						//remove enemy selected
						_selectedEnemy = null;
					
						//unhighlight the rest of the enemies
						unhighlightEnemies();
					}
				}
			}
			//peekaboo button
			else if (_selectedPlayer.getBtnClicked() == GameCharacter.PKB_BTN)
			{
				var _playerPkbText = Resources.Load("Attackable_text");
				_playerPkbText = MonoBehaviour.Instantiate(_playerPkbText);
				_playerPkbText.transform.position = _selectedPlayer.getTileReference().getSurfaceCoord();
				_playerPkbText.transform.position.y += 2;
				_playerPkbText.GetComponent(AttackableText).setAutoRemoveText("Peek-a-boo!", 45, 2);
							
				playerPeekabooList.Push(_selectedPlayer);
				
				//unselect the player
				_selectedPlayer.Deselected();
				//clear btn clicked of the character
				_selectedPlayer.removeBtnClicked();
				//unlock and allow selection of other player
				_lockSelectedPlayer = false;
				//remove player selected
				_selectedPlayer = null;
			}
			//Do nothing button
			else if (_selectedPlayer.getBtnClicked() == GameCharacter.NTH_BTN)
			{
				
			}
			//Do cancel button
			else if (_selectedPlayer.getBtnClicked() == GameCharacter.NO_BTN)
			{
				//button cancelled, allow other players to be selected
				_lockSelectedPlayer = false;
				_waitingForPlayerSelection = false;
				_waitingForEnemySelection = false;
				unhighlightEnemies();
				unhighlightPlayers();			
			}
			//Skill button
			else if (_selectedPlayer.getBtnClicked() == GameCharacter.SKILL_BTN)
			{
				//button selected, do not allow other players to be selected
				_lockSelectedPlayer = true;
				
				if(_selectedPlayer.getIsCooldown()){
				
					var _attackableText = Resources.Load("Attackable_text");
					_attackableText = MonoBehaviour.Instantiate(_attackableText);
					_attackableText.transform.position = _selectedPlayer.getTileReference().getSurfaceCoord();
					_attackableText.transform.position.y += 2;
					_attackableText.GetComponent(AttackableText).setAutoRemoveText(_selectedPlayer.getSkillCooldown()+" more turn/s", 15, 2);
					
					//unselect the player
					_selectedPlayer.Deselected();
					//clear btn clicked of the character
					_selectedPlayer.removeBtnClicked();
					
					_lockSelectedPlayer = false;
									
					//remove player selected
					_selectedPlayer = null;	
					
				}else{
					// Melee cover skill
					if(_selectedPlayer.getPlayerType() == GameCharacter.PlayerType.PLAYER_MELEE || _selectedPlayer.getPlayerType() == GameCharacter.PlayerType.PLAYER_SCOUT){
						//unselect the player
						_selectedPlayer.Deselected();
						//clear btn clicked of the character
						_selectedPlayer.removeBtnClicked();
						
						_lockSelectedPlayer = false;
						
						//use skill
						_selectedPlayer.skill();
						
						//remove player selected
						_selectedPlayer = null;			
																					
					}else if(_selectedPlayer.getPlayerType() == GameCharacter.PlayerType.PLAYER_HEALER){
						// Healer heal skill
						//show enemies that can be healed
						//just clicked
						if (!_waitingForPlayerSelection)
						{	
							//allow enemy selection
							_waitingForPlayerSelection = true;
							//find list of players within range
							var playersInRange:Array = new Array();
							var healRange = _selectedPlayer.getSkillRadius();					
							var playerIndex = 0;
							
							if (!_selectedPlayer.getIsDead())
							{
								if(!_selectedPlayer.isMaxHealth()){
									//target is within range
									playersInRange.Push(_selectedPlayer);
								}
							}
							
							for (playerIndex = 0; playerIndex < playerList.length; playerIndex++)
							{
								var dstCoordPlayers :Vector2 = playerList[playerIndex].getCoord();
								if (Vector2.Distance(_selectedPlayer.getCoord(), dstCoordPlayers) <= healRange && !playerList[playerIndex].getIsDead() && playerList[playerIndex] != _selectedPlayer)
								{
									if(!playerList[playerIndex].isMaxHealth()){
										//target is within range
										playersInRange.Push(playerList[playerIndex]);
									}
								}
							}
							//raycast to the list of players for visibility check
							playerIndex = 0;
													
							for (playerIndex = 0; playerIndex < playersInRange.length; playerIndex++)
							{
								playersInRange[playerIndex].setSelectable(true);							
							}	
							
							if(playersInRange.length == 0){
								var noHealText = Resources.Load("Attackable_text");
								noHealText = MonoBehaviour.Instantiate(noHealText);
								noHealText.transform.position = _selectedPlayer.getTileReference().getSurfaceCoord();
								noHealText.transform.position.y += 2;
								noHealText.GetComponent(AttackableText).setAutoRemoveText("No one to heal", 50, 2, Color.green);
								
								//unselect the player
								_selectedPlayer.Deselected();
								//clear btn clicked of the character
								_selectedPlayer.removeBtnClicked();
								
								_lockSelectedPlayer = false;
												
								//remove player selected
								_selectedPlayer = null;			
							}
						}
						else
						{
							//enemy selected
							if (_selectedHealTarget != null)
							{
								unhighlightPlayers();
								
								//attack the enemy
								_selectedPlayer.skill(_selectedHealTarget);
								
								_selectedHealTarget.Deselected();
								
								//unselect the player
								_selectedPlayer.Deselected();
								//clear btn clicked of the character
								_selectedPlayer.removeBtnClicked();
								//unlock and allow selection of other player
								_lockSelectedPlayer = false;						
								
								//remove player selected
								_selectedPlayer = null;			
								//remove selectedHealTarget selected
								_selectedHealTarget = null;								
							}
						}
						// End of heal
					}else{
						// all other skill attack targetting
						if (!_waitingForEnemySelection)
						{	
							//allow enemy selection
							_waitingForEnemySelection = true;
							//find list of enemies within range
							var enemiesInRangeSkill:Array = new Array();
							var atkRangeSkill = _selectedPlayer.getAttackRadius();
							var srcCoordSkill:Vector2 = _selectedPlayer.getCoord();
							
							for (var k = 0; k < enemyList.length; k++)
							{
								var dstCoordSkill :Vector2 = enemyList[k].getCoord();
								if (Vector2.Distance(srcCoordSkill, dstCoordSkill) <= atkRangeSkill && !enemyList[k].getIsDead())
								{
									//target is within range
									enemiesInRangeSkill.Push(enemyList[k]);
								}
							}
							//raycast to the list of enemies for visibility check
							var raySourceSkill:Vector3 = _selectedPlayer.getSurfaceCoord();
							layerMask = 1 << LayerMask.NameToLayer("Obstacle");	
							for (var m = 0; m < enemiesInRangeSkill.length; m++)
							{
								var rayDstSkill:Vector3 = enemiesInRangeSkill[m].getSurfaceCoord();
								var hitSkill:RaycastHit;
								//convert enemy to obstacle layer for raycasting
								enemiesInRangeSkill[m].gameObject.layer = LayerMask.NameToLayer("Obstacle");
								//raycast only to the enemy layer
								if (Physics.Raycast(raySourceSkill, rayDstSkill - raySourceSkill, hitSkill, atkRangeSkill,layerMask))
								{
									//casted enemies, setSelectable(true)
									if(hitSkill.collider.gameObject.tag.Equals("EnemyCharacter")){
										if(_selectedPlayer.getPlayerType() == GameCharacter.PlayerType.PLAYER_SPELL){
											enemiesInRangeSkill[m].setSelectable(true, "Cast Spell");
										}else{
											enemiesInRangeSkill[m].setSelectable(true, _selectedPlayer.calculateHitChance(enemiesInRangeSkill[m])
																		,enemiesInRangeSkill[m].isFlanked(_selectedPlayer));
										}
										
										enemiesInRangeSkill[m].setGridTarget(_selectedPlayer.getSkillRadius());
										
									}
								}
								enemiesInRangeSkill[m].gameObject.layer = LayerMask.NameToLayer("Enemy");
								
							}	
							
							if(enemiesInRangeSkill.length == 0){
								var noSkillRangeText = Resources.Load("Attackable_text");
								noSkillRangeText = MonoBehaviour.Instantiate(noSkillRangeText);
								noSkillRangeText.transform.position = _selectedPlayer.getTileReference().getSurfaceCoord();
								noSkillRangeText.transform.position.y += 2;
								noSkillRangeText.GetComponent(AttackableText).setAutoRemoveText("Not in range", 40, 2);
								
								//unselect the player
								_selectedPlayer.Deselected();
								//clear btn clicked of the character
								_selectedPlayer.removeBtnClicked();
								
								_lockSelectedPlayer = false;
												
								//remove player selected
								_selectedPlayer = null;			
							}
						}
						else
						{
							//enemy selected
							if (_selectedEnemy != null)
							{
							
								//unlock and allow selection of other player
								_lockSelectedPlayer = false;
								//lock state to disallow selection of other things when moving
								moveDone = false;								
								
								//attack the enemy
								_selectedPlayer.skill(_selectedEnemy);
								
								//unselect the player
								_selectedPlayer.Deselected();
								//clear btn clicked of the character
								_selectedPlayer.removeBtnClicked();
								
								//remove player selected
								_selectedPlayer = null;			
								//remove enemy selected
								_selectedEnemy = null;
							
								//unhighlight the rest of the enemies
								unhighlightEnemies();
							}
						}	
					}
				}	
			}
			
		}
	}
	public function updateEnemy(){
		//updateMelee(enemyList[5] as EnemyCharacter); //temp, must remove after bottom section is done
		var toEnd:boolean = true;
	
		if( !AImoveDone && eindex < enemyList.length )
		{
			var enemy:EnemyCharacter = enemyList[eindex];	
			var enemyType:EnemyCharacter.EnemyType = enemy.getEnemyType();
			
			if( enemy.getIsDead() )
			{
				enemyEnd();
				if( eindex >= enemyList.length )
				{
					AImoveDone = true;
					eindex = 0;
				}
			}
			
			if(!enemy.isExposed()){
				enemyEnd();
				
				if( eindex >= enemyList.length )
				{
					AImoveDone = true;
					eindex = 0;
				}
			}
			
			//Do not proceed if enemy is doing something, example moving
			if( !enemy.getIsLocked() ){		
		
				delay ++;
				if( delay > 100 )
				{
					delay = 0;
					
					if( enemy.getTurnsLeft() > 0 )
					{
						var visible:boolean = enemy.isVisible();
						//if enemy is visible. set the camera onto him first before executing 
						if( visible )
						{
							var cam = GameObject.FindWithTag("MainCamera");
							cam.GetComponent("CameraOrbit").setCameraPos(enemy.transform.position.x,enemy.transform.position.z);
						}
						else
						{
							//skip the delay
							delay = 100;
						}
						////Debug.Log("Turns: "+enemy.getTurnsLeft()+" | "+eindex);
						//Get the decision
						//var decstruct:DecisionStruct = updateArcher(enemyList[eindex] as EnemyCharacter);
						var decstruct:DecisionStruct;
						
						switch(enemyType){
							case EnemyCharacter.EnemyType.ENEMY_MELEE:
								decstruct = updateMelee(enemy);
								break;
							case EnemyCharacter.EnemyType.ENEMY_ARCHER:
								decstruct = updateArcher(enemy);
								break;
							case EnemyCharacter.EnemyType.ENEMY_HEALER:
								decstruct = updateHealer(enemy);
								break;
							case EnemyCharacter.EnemyType.ENEMY_SPELL:
								decstruct = updateSpellcaster(enemy);
								break;
							default:
								decstruct = updateArcher(enemy);
								break;
						}						
						
						Debug.Log("Enemy Decision: "+eindex+" | "+decstruct.getDecision());
						if( decstruct.getDecision() == AIDecision.AIMOVE )
						{				
							enemy.setIsLocked(true); //will toogle false after AI reached his destination
							//move the enemy
							enemy.moveTo(decstruct.getMoveTile());
						
							//enemy can have another move again if they have 2 moves							
							if( enemy.getTurnsLeft() > 1 )
							{							
								toEnd = false;
								//return;
								//i--;
								//continue; //continue to next loop so enemyEnd dont get called
							}
						}
						else if( decstruct.getDecision() == AIDecision.AIATTACK )
						{
							//Debug.Log("Attack AI to "+decstruct.getPlayerCharacter());
							enemy.setIsLocked(true);
							//attack the enemy
							enemy.attack(decstruct.getPlayerCharacter(), Projectile.NORMAL);
						}
						else if( decstruct.getDecision() == AIDecision.AIPEEKABOO )
						{
							Debug.Log("AI Peek-a-boo");
							
							var _attackableText = Resources.Load("Attackable_text");
							_attackableText = MonoBehaviour.Instantiate(_attackableText);
							_attackableText.transform.position = enemy.getTileReference().getSurfaceCoord();
							_attackableText.transform.position.y += 2;
							_attackableText.GetComponent(AttackableText).setAutoRemoveText("Peek-a-boo!", 45, 2);
							
							enemyPeekabooList.Push(enemy);
							enemy.setPeekabooEnabled(true);
							//add self to peekaboo
							//set self to peekaboo
						}
						else if( decstruct.getDecision() == AIDecision.AI_ATTACKSKILL )
						{
							Debug.Log("AI ATTACK SKILL");
							enemy.setIsLocked(true);
							//use skill on the enemy
							enemy.skill(decstruct.getPlayerCharacter());
						}
						else if( decstruct.getDecision() == AIDecision.AI_BUFFSKILL )
						{
							Debug.Log("AI BUFF SKILL");
							enemy.setIsLocked(true);
							//use skill on the enemy
							enemy.skill(decstruct.getEnemyAllyCharacter());
						}
						if( toEnd )
						{
							enemyEnd();
						}
					}
					
					if( toEnd )
					{
						//Debug.Log("LENGTH " + enemyList.length);
						//Debug.Log("EINDEX " + eindex);
						//Debug.Log("Enemies Done " + numEnemiesDone);
						if( eindex >= enemyList.length )
						{
							//Debug.Log("Execute AI3");
							AImoveDone = true;
							eindex = 0;
						}
					}
				}
			}
		}
	}
		
	// AI Decision Tree
	function updateMelee(selectedEnemy:EnemyCharacter){
		var decstruct:DecisionStruct = new DecisionStruct();
		
		// If enemy is visible, continue
		if(selectedEnemy.isExposed()){
			
			//initialize AI
			var aiCheck:AIMelee = new AIMelee(selectedEnemy, playerList);
			
			//find list of players within enemy range			
			var isInRange:boolean = aiCheck.getIsInRange();
			var playersInRange:Array = aiCheck.getPlayersInRange();
			var closestPlayer:GameCharacter = aiCheck.getClosestPlayer();
			//Debug.Log("AI range: "+atkRange);
						
			// Check if in cover or flanked by player
			// If in cover, check players in range			
			var attackDesire:AttackDesire;
			var canAttack;
			var moveToCoverTile:Tile;
			
			if((selectedEnemy.isInCover() && !aiCheck.isFlankedByPlayer() && closestPlayer != null) || aiCheck.getClosestDistance() <= selectedEnemy.getEngageRadius()){							
				Debug.Log("Melee Decision 1");
			//find list of players within enemy range, check attack
				if(isInRange){
					//Debug.Log("AI distance: "+closestDistance);
					// If can attack player, check moves left
					attackDesire = new AttackDesire(selectedEnemy.getAttackPercent());
					canAttack = attackDesire.canAttack(selectedEnemy.getHealth(), selectedEnemy.calculateHitChance(closestPlayer));			
					//Debug.Log("AI can attack: "+canAttack+" | "+selectedEnemy.calculateHitChance(closestPlayer));
					
					if(canAttack){
						decstruct.setPlayerCharacter(closestPlayer);
						// If skill not on cd, use enrage
						if(!selectedEnemy.getIsCooldown()){
							decstruct.setDecision(AIDecision.AI_ATTACKSKILL);	
						}else{
							// else attack					
							decstruct.setDecision(AIDecision.AIATTACK);						
						}					
					}else{
						// If cannot attack player, peek-a-boo or move	
						decstruct.setDecision(AIDecision.AIPEEKABOO);	
					}	
				}else{
					//if within engage radius, run straight to enemy
					//decstruct.setMoveTile(getCoverTile(selectedEnemy, 0, closestPlayer.getSurfaceCoord(), closestPlayer.getCoord()));
					moveToCoverTile = aiCheck.getForwardCoverTile(mapReference);
					
					Debug.Log("Melee Decision 2");
					
					if(moveToCoverTile != null){
						decstruct.setMoveTile(moveToCoverTile);
						decstruct.setDecision(AIDecision.AIMOVE);
					}else{
						// If no valid movement, peek-a-boo	
						decstruct.setDecision(AIDecision.AIPEEKABOO);
					}
				}				
			}else{
				// If not in cover, move to cover
				// If players not in range, move to cover
				//if within engage radius, run straight to enemy
				moveToCoverTile = aiCheck.getCoverTile(mapReference);
				
				Debug.Log("Melee Decision 4");
				
				if(moveToCoverTile != null){
					decstruct.setMoveTile(moveToCoverTile);
					decstruct.setDecision(AIDecision.AIMOVE);
				}else{
					
					Debug.Log("Melee Decision 5");
					
					if(isInRange){
						//Debug.Log("AI distance: "+closestDistance);
						// If can attack player, check moves left
						attackDesire = new AttackDesire(selectedEnemy.getAttackPercent());
						canAttack = attackDesire.canAttack(selectedEnemy.getHealth(), selectedEnemy.calculateHitChance(closestPlayer));			
						//Debug.Log("AI can attack: "+canAttack+" | "+selectedEnemy.calculateHitChance(closestPlayer));
						
						Debug.Log("Melee Decision 6");
						
						if(canAttack){
							decstruct.setPlayerCharacter(closestPlayer);
							// If skill not on cd, use enrage
							if(!selectedEnemy.getIsCooldown()){
								decstruct.setDecision(AIDecision.AI_ATTACKSKILL);	
							}else{
								// else attack					
								decstruct.setDecision(AIDecision.AIATTACK);						
							}					
						}else{
							// If cannot attack player, peek-a-boo or move	
							decstruct.setDecision(AIDecision.AIPEEKABOO);	
						}	
					}else{
						// If not in range to attack, peek-a-boo	
						decstruct.setDecision(AIDecision.AIPEEKABOO);
					}
				}
			}					
		}else{
			// If enemy is not visible, patrol
			decstruct.setDecision(AIDecision.PATROL);
		}
		
		return decstruct;
	}
	function updateArcher(selectedEnemy:EnemyCharacter){
		var decstruct:DecisionStruct = new DecisionStruct();
		
		// If enemy is visible, continue
		if(selectedEnemy.isExposed()){
			
			//initialize AI
			var aiCheck:AIArcher = new AIArcher(selectedEnemy, playerList);
			
			//find list of players within enemy range			
			var isInRange:boolean = aiCheck.getIsInRange();
			var playersInRange:Array = aiCheck.getPlayersInRange();
			var closestPlayer:GameCharacter = aiCheck.getClosestPlayer();
			//Debug.Log("AI range: "+atkRange);
						
			// Check if in cover or flanked by player
			// If in cover, check players in range			
			var attackDesire:AttackDesire;
			var canAttack;
			var moveToCoverTile:Tile;
			
			
			// Check if in cover or flanked by player
			// If in cover, check players in range			
			if(selectedEnemy.isInCover() && !aiCheck.isFlankedByPlayer() && closestPlayer != null){		
								
				// If players not within retreat range, check attack range
				if(!aiCheck.getIsRetreat()){
					// If players dont have 80% hit chance, check attack range				
					var playerHitChance:GameCharacter = aiCheck.getHighestHitPlayer();
					var checkCanAttack:boolean = false;
					
					//Debug.Log("Decision1: "+playerHitChance);
					
					if(playerHitChance == null){
						checkCanAttack = true;
					}else{
						// If players have 80% hit chance, blind enemy
						// check skill CD
						if(!selectedEnemy.getIsCooldown() && playerHitChance.getAttackChanceModifier() >= 0){	
							decstruct.setPlayerCharacter(playerHitChance);
							decstruct.setDecision(AIDecision.AI_ATTACKSKILL);
						}else{
							checkCanAttack = true;
						}
					}										
					
					//find list of players within enemy range, check attack
					if(checkCanAttack){
						if(isInRange){							
							// If can attack player, check moves left
							attackDesire = new AttackDesire(selectedEnemy.getAttackPercent());
							canAttack = attackDesire.canAttack(selectedEnemy.getHealth(), selectedEnemy.calculateHitChance(closestPlayer));			
							//Debug.Log("AI can attack: "+canAttack+" | "+selectedEnemy.calculateHitChance(closestPlayer));
							
							//Debug.Log("Decision2: "+attackDesire);
							
							if(canAttack){				
								decstruct.setPlayerCharacter(closestPlayer);
								decstruct.setDecision(AIDecision.AIATTACK);						
							}else{
								// If cannot attack player, peek-a-boo or move	
								decstruct.setDecision(AIDecision.AIPEEKABOO);
							}
							
						}else{
							//if within engage radius, run straight to enemy
							//decstruct.setMoveTile(getCoverTile(selectedEnemy, 0, closestPlayer.getSurfaceCoord(), closestPlayer.getCoord()));
							moveToCoverTile = aiCheck.getForwardCoverTile(mapReference);
							//Debug.Log("Decision3: "+moveToCoverTile);
							if(moveToCoverTile != null){
								decstruct.setMoveTile(moveToCoverTile);
								decstruct.setDecision(AIDecision.AIMOVE);
							}else{
								// If no valid movement, peek-a-boo	
								decstruct.setDecision(AIDecision.AIPEEKABOO);
							}
						}
					}
					
				}else{
					// if no retreat cover tile, run far away from enemy
					var retreatCoverTile:Tile = aiCheck.getRetreatCoverTile(mapReference);
					//Debug.Log("Decision4: "+retreatCoverTile);
					
					// If no place to retreat to, try to attack
					if(retreatCoverTile != null){
						decstruct.setMoveTile(retreatCoverTile);
						decstruct.setDecision(AIDecision.AIMOVE);
					}else{
						// If no valid movement, try to attack
						if(isInRange){
							// If in range, attack player if possible
							attackDesire = new AttackDesire(selectedEnemy.getAttackPercent());
							canAttack = attackDesire.canAttack(selectedEnemy.getHealth(), selectedEnemy.calculateHitChance(closestPlayer));			
							//Debug.Log("AI can attack: "+canAttack+" | "+selectedEnemy.calculateHitChance(closestPlayer));
							
							if(canAttack){
								decstruct.setPlayerCharacter(closestPlayer);
								decstruct.setDecision(AIDecision.AIATTACK);											
							}else{
								// If cannot attack player, peek-a-boo or move	
								decstruct.setDecision(AIDecision.AIPEEKABOO);	
							}	
						}else{
							// If not in range to attack, peek-a-boo	
							decstruct.setDecision(AIDecision.AIPEEKABOO);
						}
					}
					
				}
				
			}else{
				// If not in cover, move to cover				
				moveToCoverTile = aiCheck.getCoverTile(mapReference);
				
				//Debug.Log("Decision5: "+moveToCoverTile);
				
				if(moveToCoverTile != null){
					decstruct.setMoveTile(moveToCoverTile);
					decstruct.setDecision(AIDecision.AIMOVE);
				}else{
					// If no valid movement, try to attack
					if(isInRange){
						// If in range, attack player if possible
						attackDesire = new AttackDesire(selectedEnemy.getAttackPercent());
						canAttack = attackDesire.canAttack(selectedEnemy.getHealth(), selectedEnemy.calculateHitChance(closestPlayer));			
						//Debug.Log("AI can attack: "+canAttack+" | "+selectedEnemy.calculateHitChance(closestPlayer));
						
						if(canAttack){
							decstruct.setPlayerCharacter(closestPlayer);
							decstruct.setDecision(AIDecision.AIATTACK);											
						}else{
							// If cannot attack player, peek-a-boo or move	
							decstruct.setDecision(AIDecision.AIPEEKABOO);	
						}	
					}else{
						// If not in range to attack, peek-a-boo	
						decstruct.setDecision(AIDecision.AIPEEKABOO);
					}
				}
			}					
		}else{
			// If enemy is not visible, patrol
			decstruct.setDecision(AIDecision.PATROL);
		}
		
		return decstruct;
	}
	function updateHealer(selectedEnemy:EnemyCharacter){
		var decstruct:DecisionStruct = new DecisionStruct();
		
		// If enemy is visible, continue
		if(selectedEnemy.isExposed()){
			
			var aiCheck:AIHealer = new AIHealer(selectedEnemy, playerList, enemyList);
			
			//find list of players within enemy range			
			var isInRange:boolean = aiCheck.getIsInRange();
			var playersInRange:Array = aiCheck.getPlayersInRange();
			var closestPlayer:GameCharacter = aiCheck.getClosestPlayer();
			//Debug.Log("AI range: "+atkRange);
			
			//find allies with low health
			var closestAllyInDanger:EnemyCharacter = aiCheck.getClosestAllyInDanger();
			var closestAllyDistance = aiCheck.getClosestAllyDistance();
			
			// Check if in cover or flanked by player
			// If in cover, check players in range			
			var attackDesire:AttackDesire;
			var canAttack;
			var moveToCoverTile:Tile;
			var checkCanAttack:boolean = false;
			
			// Check if in cover or flanked by player
			// If in cover, check players in range			
			if(selectedEnemy.isInCover() && !aiCheck.isFlankedByPlayer() && closestPlayer != null){		
				// Check if conditions satisfy for healer to attack
				checkCanAttack = false;
				Debug.Log("Decision 1");
				// If there are no allies less than 70% hp, check for attack
				if(closestAllyInDanger == null || selectedEnemy.getIsCooldown()){				
					checkCanAttack = true;
				}else{
					// attempt to heal player if allies less thatn 50% hp;
					if(aiCheck.getIsInHealRange()){
						Debug.Log("Decision 2");
						//Check skill CD
						//Use heal if possible on closestAllyInDanger
						//if skill on CD, set checkCanAttack to true
						if(!selectedEnemy.getIsCooldown()){
							decstruct.setEnemyAllyCharacter(closestAllyInDanger);
							decstruct.setDecision(AIDecision.AI_BUFFSKILL);
						}else{
							checkCanAttack = true;
						}
					}else{
						Debug.Log("Decision 3");
						// if not in heal range
						// move to cover nearest to lowest Health ally
						moveToCoverTile = aiCheck.getForwardCoverTile(mapReference);
							
						if(moveToCoverTile != null){
							decstruct.setMoveTile(moveToCoverTile);
							decstruct.setDecision(AIDecision.AIMOVE);
						}else{
							// If no valid movement, peek-a-boo	
							decstruct.setDecision(AIDecision.AIPEEKABOO);
						}
					}					
				}	
				
				//find list of players within enemy range, check attack
				if(checkCanAttack){
					Debug.Log("Decision 4");
					if(isInRange){
						// If can attack player, check moves left
						attackDesire = new AttackDesire(selectedEnemy.getAttackPercent());
						canAttack = attackDesire.canAttack(selectedEnemy.getHealth(), selectedEnemy.calculateHitChance(closestPlayer));			
						//Debug.Log("AI can attack: "+canAttack+" | "+selectedEnemy.calculateHitChance(closestPlayer));
						
						if(canAttack){
							decstruct.setPlayerCharacter(closestPlayer);
							decstruct.setDecision(AIDecision.AIATTACK);						
						}else{
							// If cannot attack player, peek-a-boo or move	
							decstruct.setDecision(AIDecision.AIPEEKABOO);
						}
						
					}else{
						// If players not in range, move to cover
						// If not in cover, move to cover
						// move to cover nearest to lowest Health ally
						// if not in heal range
						// move to cover nearest to lowest Health ally
						moveToCoverTile = aiCheck.getCoverTile(mapReference);
						Debug.Log("Decision 5");
						if(moveToCoverTile != null){
							decstruct.setMoveTile(moveToCoverTile);
							decstruct.setDecision(AIDecision.AIMOVE);
						}else{
							// If no valid movement, peek-a-boo	
							decstruct.setDecision(AIDecision.AIPEEKABOO);
						}
					}
				}
				
			}else{
				// If not in cover, move to cover								
				moveToCoverTile = aiCheck.getCoverTile(mapReference);
				Debug.Log("Decision 6");	
				if(moveToCoverTile != null){
					decstruct.setMoveTile(moveToCoverTile);
					decstruct.setDecision(AIDecision.AIMOVE);
				}else{
				
					checkCanAttack = false;
					Debug.Log("Decision 7");
					// If there are no allies less than 70% hp, check for attack
					if(closestAllyInDanger == null || selectedEnemy.getIsCooldown()){				
						checkCanAttack = true;
					}else{
						// attempt to heal player if allies less thatn 50% hp;
						if(aiCheck.getIsInHealRange()){
							Debug.Log("Decision 8");
							//Check skill CD
							//Use heal if possible on closestAllyInDanger
							//if skill on CD, set checkCanAttack to true
							if(!selectedEnemy.getIsCooldown()){
								decstruct.setEnemyAllyCharacter(closestAllyInDanger);
								decstruct.setDecision(AIDecision.AI_BUFFSKILL);
							}else{
								checkCanAttack = true;
							}
						}else{
							// if not in heal range
							// move to cover nearest to lowest Health ally
							moveToCoverTile = aiCheck.getForwardCoverTile(mapReference);
								
							if(moveToCoverTile != null){
								decstruct.setMoveTile(moveToCoverTile);
								decstruct.setDecision(AIDecision.AIMOVE);
							}else{
								// If no valid movement, peek-a-boo	
								decstruct.setDecision(AIDecision.AIPEEKABOO);
							}
						}					
					}
					
					if(checkCanAttack){
						Debug.Log("Decision 9");
						// If no valid movement, try to attack
						if(isInRange){
							Debug.Log("Decision 10");
							// If in range, attack player if possible
							attackDesire = new AttackDesire(selectedEnemy.getAttackPercent());
							canAttack = attackDesire.canAttack(selectedEnemy.getHealth(), selectedEnemy.calculateHitChance(closestPlayer));			
							//Debug.Log("AI can attack: "+canAttack+" | "+selectedEnemy.calculateHitChance(closestPlayer));
							
							if(canAttack){
								decstruct.setPlayerCharacter(closestPlayer);
								decstruct.setDecision(AIDecision.AIATTACK);											
							}else{
								// If cannot attack player, peek-a-boo or move	
								decstruct.setDecision(AIDecision.AIPEEKABOO);	
							}	
						}else{
							// If not in range to attack, peek-a-boo	
							decstruct.setDecision(AIDecision.AIPEEKABOO);
						}
					}
				}
			}					
		}else{
			// If enemy is not visible, patrol
			decstruct.setDecision(AIDecision.PATROL);
		}
		
		return decstruct;
	}
	function updateSpellcaster(selectedEnemy:EnemyCharacter){
		var decstruct:DecisionStruct = new DecisionStruct();
		
		// If enemy is visible, continue
		if(selectedEnemy.isExposed()){
			//Debug.Log("Decision 1");
			//initialize AI
			var aiCheck:AISpellcaster = new AISpellcaster(selectedEnemy, playerList);
			
			//find list of players within enemy range			
			var isInRange:boolean = aiCheck.getIsInRange();
			var playersInRange:Array = aiCheck.getPlayersInRange();
			var closestPlayer:GameCharacter = aiCheck.getClosestPlayer();
						
			// Check if in cover or flanked by player
			// If in cover, check players in range			
			var attackDesire:AttackDesire;
			var canAttack;
			var moveToCoverTile:Tile;

			// Check if in cover or flanked by player
			// If in cover, check players in range			
			if(selectedEnemy.isInCover() && !aiCheck.isFlankedByPlayer() && closestPlayer != null){	
				//Debug.Log("Decision 2");			
				// If players not within retreat range, check attack range
				if(!aiCheck.getIsRetreat()){
					//Debug.Log("Decision 3");
					//find list of players within enemy range, check attack
					if(isInRange){
						// If can attack player, check moves left
						attackDesire = new AttackDesire(selectedEnemy.getAttackPercent());
						canAttack = attackDesire.canAttack(selectedEnemy.getHealth(), selectedEnemy.calculateHitChance(closestPlayer));			
						//Debug.Log("AI can attack: "+canAttack+" | "+selectedEnemy.calculateHitChance(closestPlayer));
						
						if(canAttack){
							// If skill not on cd, use spell
							// else attack							
							decstruct.setPlayerCharacter(closestPlayer);
							
							if(!selectedEnemy.getIsCooldown() && aiCheck.canCastSpell(mapReference)){
								decstruct.setPlayerCharacter(aiCheck.getClosestPlayer());
								decstruct.setDecision(AIDecision.AI_ATTACKSKILL);
							}else{
								decstruct.setDecision(AIDecision.AIATTACK);
							}						
						}else{
							// If cannot attack player, peek-a-boo or move	
							decstruct.setDecision(AIDecision.AIPEEKABOO);
						}
						
					}else{
						// If players not in range, move to cover
						// If not in cover, move to cover
						//if within engage radius, run straight to enemy
						//decstruct.setMoveTile(getCoverTile(selectedEnemy, 0, closestPlayer.getSurfaceCoord(), closestPlayer.getCoord()));
						moveToCoverTile = aiCheck.getForwardCoverTile(mapReference);
						//Debug.Log("Decision 4");
						if(moveToCoverTile != null){
							decstruct.setMoveTile(moveToCoverTile);
							decstruct.setDecision(AIDecision.AIMOVE);
						}else{
							// If no valid movement, peek-a-boo	
							decstruct.setDecision(AIDecision.AIPEEKABOO);
						}
					}
				}else{
					// if no retreat cover tile, run far away from enemy
					var retreatCoverTile:Tile = aiCheck.getRetreatCoverTile(mapReference);
					//Debug.Log("Decision 5");
					decstruct.setMoveTile(retreatCoverTile);
					decstruct.setDecision(AIDecision.AIMOVE);
				}
				
			}else{			
				// If not in cover, move to cover				
				moveToCoverTile = aiCheck.getCoverTile(mapReference);
				//Debug.Log("Decision 6");
				if(moveToCoverTile != null){
					decstruct.setMoveTile(moveToCoverTile);
					decstruct.setDecision(AIDecision.AIMOVE);
				}else{
					// If no valid movement, try to attack
					if(isInRange){
						// If in range, attack player if possible
						attackDesire = new AttackDesire(selectedEnemy.getAttackPercent());
						canAttack = attackDesire.canAttack(selectedEnemy.getHealth(), selectedEnemy.calculateHitChance(closestPlayer));			
						//Debug.Log("AI can attack: "+canAttack+" | "+selectedEnemy.calculateHitChance(closestPlayer));
						
						if(canAttack){
							decstruct.setPlayerCharacter(closestPlayer);
							decstruct.setDecision(AIDecision.AIATTACK);											
						}else{
							// If cannot attack player, peek-a-boo or move	
							decstruct.setDecision(AIDecision.AIPEEKABOO);	
						}	
					}else{
						// If not in range to attack, peek-a-boo	
						decstruct.setDecision(AIDecision.AIPEEKABOO);
					}
				}
			}					
		}else{
			// If enemy is not visible, patrol
			decstruct.setDecision(AIDecision.PATROL);
		}
		
		return decstruct;
	}
	
	// End of AI Decision Tree
	function getPlayers()
	{
		return playerList;
	}
	function getEnemies()
	{
		return enemyList;
	}
	
	function isMoveDone()
	{
		return moveDone;
	}
	
	function setMoveDone(done:boolean)
	{
		moveDone = done;
	}
	
	function setAImoveDone(done:boolean)
	{
		AImoveDone = done;
	}
	
	function setSelectedPlayer(character:GameCharacter):boolean
	{	
		//can only select player if no other characters moving
		if (moveDone && !_lockSelectedPlayer)
		{
		 	if (_selectedPlayer != null)
		 		_selectedPlayer.Deselected();
			_selectedPlayer = character;		 				 	
			
			return true;
		}
		if (_waitingForPlayerSelection && character.isSelectable())
		{
			_selectedHealTarget = character;
			return true;
		}
		_selectedHealTarget = null;
		return false;
	}
	
	function getSelectedPlayer()
	{
		return _selectedPlayer;
	}
	
	function setSelectedEnemy(enemy:EnemyCharacter):boolean
	{
		if (_waitingForEnemySelection)
		{
			_selectedEnemy = enemy;
			return true;
		}
		//force set to null incase
		_selectedEnemy = null;
		return false;
	}
	
	
	function characterEnd()
	{
		numPlayersDone++;
		Debug.Log("numPlayersDone:" + numPlayersDone);
	}
	
	function enemyEnd()
	{
		delay = -50;
		eindex++;
		numEnemiesDone++;
	}
	
	function isEndOfPlayerTurn()
	{
		//if all players done and none is moving
		if ((numPlayersDone+numPlayersDead) >= playerList.length && moveDone)
		{
			//reset current selection
			_selectedPlayer = null;
			return true;
		}
		
		return false;
	}
	
	function isEndOfEnemyTurn()
	{
		//if all players done and none is moving
		if (numEnemiesDone >= enemyList.length && AImoveDone)
		{		
			Debug.Log("End AI");		
			numEnemiesDone = 0;
			eindex = 0; 
			return true;
		}
		return false;
	}
	
	//Player Reset
	function resetTurn(){
		_lockSelectedPlayer = false;
		numPlayersDone = 0; 
		playerPeekabooList = new Array();
		for (var i:int = 0; i < playerList.length; i++){
			if( !playerList[i].getIsDead() )
			{
				playerList[i].resetTurn();
						
				//Set camera position on first playable character
				var cam = GameObject.FindWithTag("MainCamera");
				cam.GetComponent("CameraOrbit").setCameraPos(playerList[0].transform.position.x,playerList[0].transform.position.z);
			}
		}
	}
	//Enemy Reset
	function resetEnemyTurn(){
		numEnemiesDone = 0; 
		enemyPeekabooList = new Array();
		eindex = 0;
		for (var i:int = 0; i < enemyList.length; i++){
			enemyList[i].resetTurn();
		}
	}
	
	function unhighlightPlayers()
	{
		for (var i = 0; i < playerList.length; i++)
		{
			playerList[i].setSelectable(false);
		}
		
		//disallow selection of enemies
		_waitingForPlayerSelection = false;
	}
	
	function unhighlightEnemies()
	{
		for (var i = 0; i < enemyList.length; i++)
		{
			//enemyList[i].setSelectable(false, 0, false);
			enemyList[i].resetSelectable();
			enemyList[i].removeGridTarget();
		}
		
		//disallow selection of enemies
		_waitingForEnemySelection = false;
	}
	
	function clearPlayerSelectionLock()
	{
		_lockSelectedPlayer = false;
	}
	
	function getEnemyListLength() 
	{
		if( enemyList != null )
			return enemyList.length;
		else
			return 0;
	}
	
	function getPlayerListLength()
	{
		if( playerList != null )
			return playerList.length;
		else
			return 0;
	}
	
	function getEnemyPeekabooList()
	{
		return enemyPeekabooList;
	}	
	
	function getPlayerPeekabooList()
	{
		return playerPeekabooList;
	}
	
	function setPauseMode(b:boolean) 
	{
		for( var i = 0; i < playerList.length; i++ )
		{
			playerList[i].setPause(b);
		}
	/*	for ( i = 0; i < enemyList.length; i++)
		{
			enemyList[i].setPause(b);
		}*/
	
		pauseMode = b;
	}
	
	function increasePlayerDeathCount()
	{
		numPlayersDead += 1;
	}
	
	function setNextSelectedPlayer() 
	{	
		var toselect:int = 0;
	
		for( var i = 0 ;i < playerList.length * 2; i++ )
		{
			//Find the selected player
			if( _selectedPlayer != null && _selectedPlayer == playerList[i%playerList.length] )
			{
				if (_selectedPlayer.getBtnClicked() == GameCharacter.MOVE_BTN){
					mapReference.unhighlightTiles();
				}else if (_selectedPlayer.getBtnClicked() == GameCharacter.ATK_BTN || _selectedPlayer.getBtnClicked() == GameCharacter.SKILL_BTN){
					unhighlightEnemies();
					unhighlightPlayers();
				}
				
				//unselect the player
				_selectedPlayer.Deselected();
				//clear btn clicked of the character
				_selectedPlayer.removeBtnClicked();
				//unlock and allow selection of other player
				_lockSelectedPlayer = false;
				//release
				moveDone = true;								
				
				//remove player selected
				_selectedPlayer = null;	
				
				//toselect = i%playerList.length + 1;
			}
			//If no selected player, get the nearest one
			else if( _selectedPlayer == null && !playerList[i%playerList.length].getIsDead() && playerList[i%playerList.length].getTurnsLeft() > 0 && setSelectedPlayer(playerList[i%playerList.length]) )
			{
				toselect = i%playerList.length;
				playerList[toselect].Selected();	
				
				//Set camera position on character
				var cam = GameObject.FindWithTag("MainCamera");
				cam.GetComponent("CameraOrbit").setCameraPos(playerList[toselect].transform.position.x,playerList[toselect].transform.position.z);
				
				break;
			}
		}
	}
	function resetSelectedPlayer()
	{
		if( _selectedPlayer != null )
		{
			if (_selectedPlayer.getBtnClicked() == GameCharacter.MOVE_BTN){
				mapReference.unhighlightTiles();
			}else if (_selectedPlayer.getBtnClicked() == GameCharacter.ATK_BTN || _selectedPlayer.getBtnClicked() == GameCharacter.SKILL_BTN){
				unhighlightEnemies();
				unhighlightPlayers();
			}
			
			//unselect the player
			_selectedPlayer.Deselected();
			//clear btn clicked of the character
			_selectedPlayer.removeBtnClicked();
			//unlock and allow selection of other player
			_lockSelectedPlayer = false;
			//release
			moveDone = true;								
			
			//remove player selected
			_selectedPlayer = null;			
		}
	}
}
